// This package makes it easier to talk to the Index Server.
//
// You can install this package by running:
//
//   $ goinstall cloud9lib.googlecode.com/hg/index
//
package index

import (
	"net/http"

	"io/ioutil"
	"net/url"
	"strings"
)

// this is useful if you want public access to the index server,
// but this is obviously very very dangerous
//const INDEX_URL = "http://index.cloud9lib.net"

const INDEX_URL = "http://localhost:8006"

// Registers a bucket as belonging to the storage node at urlstr.
// Storage nodes should call this when they create a new bucket.
func AddBucket(bucket, urlstr string) error {

	bucket = url.QueryEscape(bucket)

	reader := strings.NewReader(urlstr)
	req, err := http.NewRequest("PUT", INDEX_URL+"/bucket?id="+bucket, reader)

	if err != nil {
		return err
	}

	req.Header.Set("Content-type", "text/plain")
	resp, err := http.DefaultClient.Do(req)

	if err == nil {
		resp.Body.Close()
	}

	return err
}

// Queries the index to determine where the given bucket is stored.
// Returns a URL string.
func WhereIs(bucket string) (string, error) {

	bucket = url.QueryEscape(bucket)

	resp, err := http.Get(INDEX_URL + "/bucket?id=" + bucket)

	if err != nil || resp.StatusCode != 200 {
		return "", err
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)

	return string(body), err
}

// Registers a new request multiplexer.
// Should be called by the mux itself upon waking up.
func AddMux(urlstr string) error {

	reader := strings.NewReader(urlstr)
	id := url.QueryEscape(urlstr)

	req, err := http.NewRequest("PUT", INDEX_URL+"/mux?id="+id, reader)

	if err != nil {
		return err
	}

	req.Header.Set("Content-type", "text/plain")
	resp, err := http.DefaultClient.Do(req)

	if err == nil {
		resp.Body.Close()
	}

	return err
}

func AddRoute(pattern, urlstr string) error {

	pattern = url.QueryEscape(pattern)

	reader := strings.NewReader(urlstr)
	req, err := http.NewRequest("PUT", INDEX_URL+"/route?id="+pattern, reader)

	if err != nil {
		return err
	}

	req.Header.Set("Content-type", "text/plain")
	resp, err := http.DefaultClient.Do(req)

	if err == nil {
		defer resp.Body.Close()
	}

	return err
}

func DeleteRoute(pattern string) error {

	pattern = url.QueryEscape(pattern)

	req, err := http.NewRequest("DEL", INDEX_URL+"/route?id="+pattern, nil)

	if err != nil {
		return err
	}

	req.Header.Set("Content-type", "text/plain")
	resp, err := http.DefaultClient.Do(req)

	if err == nil {
		defer resp.Body.Close()
	}

	return err
}

// Queries the index for a route entry.  This only works behind the cloud firewall.
// Returns a URL string.
func Route(pattern string) (string, error) {

	pattern = url.QueryEscape(pattern)

	resp, err := http.Get("http://localhost:8006/route?id=" + pattern)

	if err != nil || resp.StatusCode != 200 {
		return "", err
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)

	return string(body), err
}
